package com.walker.handler;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.MethodParameter;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.alibaba.fastjson.JSON;
import com.walker.anno.ResponseResult;

@ControllerAdvice(basePackages = {"com.walker.controller"})
public class ResponseResultHandler implements ResponseBodyAdvice<Object>{

	private static final Log log = LogFactory.getLog(ResponseResultHandler.class);
	
	private static final String RESOPNSE_RESULT_ANNO = "responseResultAnno";
	
	@Override
	public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
		ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = sra.getRequest();
		ResponseResult responseResult = (ResponseResult)request.getAttribute(RESOPNSE_RESULT_ANNO);

		return responseResult == null ? false : true;
	}

	/**
	   只有使用了ResponseResult注解才执行
	   返回值若没有使用ResponseData封装，则自动加上
	 */
	@Override
	public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
			Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,ServerHttpResponse response) {
		ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
		HttpServletRequest httpServletRequest = sra.getRequest();
		ResponseResult responseResult = (ResponseResult)httpServletRequest.getAttribute(RESOPNSE_RESULT_ANNO);
		if(body instanceof ResponseData) {
			return body;
		}
		
		if (body instanceof String) {//解决ctrl返回string报错问题，后续全部改造完统一放在WebMvcConfig里解决更省事
			return JSON.toJSONString(ResponseData.success(body,responseResult.msg()));
		}
		return ResponseData.success(body,responseResult.msg());
	}

	/**
	 * 手动抛出已知错误提示信息
	 * @param e
	 * @return
	 */
	@ExceptionHandler(BizException.class)
    @ResponseBody
    public ResponseData exceptionHandler(BizException e) {
		if(log.isErrorEnabled()) {
			log.error(e.getMessage(),e);
		}
        return ResponseData.failure(e.getMessage());
    }
	
	/**
	 * 调用系统异常信息
	 * @param e
	 * @return
	 */
	@ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseData exceptionHandler(Exception e) {
		if(log.isErrorEnabled()) {
			log.error(e.getMessage(),e);
		}
        return ResponseData.failure(e.getMessage());
    }
	
	@ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseBody
    public ResponseData dataIntegrityViolationException(Exception e) {
		if(log.isErrorEnabled()) {
			log.error(e.getMessage(),e);
		}
		if(e.getMessage().contains("foreign key constraint")){
			return ResponseData.failure("已被使用，无法删除！");
		}
        return ResponseData.failure(e.getMessage());
    }
}
